昨天談到新增「部分退款」狀態時,售後追蹤排程也需要調整,才能繼續納入仍有有效購買的訂單。確認修改範圍後,接著會遇到另一個問題:新增狀態與修改排程,應該放在同一個提交嗎?
一邊是退款功能,一邊是每天執行的排程,看起來是兩件事。但它們共同完成的,是讓系統支援部分退款,同時維持原本的售後追蹤資格。
Git存的是差異,而提交的組織方式,決定了後來的人是看懂意圖,還是在猜測歷史。
依目的切分,把必要的依賴留在一起
假設退款功能與排程都在同一個程式庫,這次準備一起提供部分退款功能。將新狀態、退款處理、畫面呈現、排程篩選與對應測試放在同一個提交,是合理的安排。
如果只留下退款功能的修改,新狀態就會進入系統,排程卻仍沿用舊條件。排程雖然沒有參與退款操作,仍是完成這項變更所需要的一部分。
原子提交強調的正是這種邏輯完整性:把完成同一項變更所需的修改放在一起,讓取得這個版本的人可以編譯與驗證. 它不必依資料夾或檔案數量切開。
同一項需求也可以分成有順序的提交。例如先加入新狀態的辨識能力,讓排程能同時處理新舊資料,再於後續提交開放部分退款。只要每個中間版本都能獨立編譯與驗證、依賴清楚,就不是把功能硬拆成缺少零件的片段。
如果排程與退款服務分屬不同程式庫,Git在實體層面上無法跨庫建立提交。此時需要透過同一張需求單與拉請求(Pull Request)關聯串起相關變更,交代版本依賴。程式變更如何組織,和上線時如何配合,始終是兩回事。
需要調整時,不必重新拆解整批工作
假設修改售後排程時,也順便更換了簡訊套件或調整命名。這些工作雖然同時完成,卻不一定是支援部分退款的必要條件。
若套件更換能獨立成立,就應該另外提交。日後新套件發生問題時,才能集中檢視相關差異,同時保留部分退款訂單的追蹤條件。
即使後續程式已經使用新套件的介面無法直接撤回,清楚的歷史也能幫你迅速定位需要配合調整的地方。不用在退款金額、狀態轉換、排程篩選與大量改名之間,逐行猜測哪些才屬於這次要撤掉的行為。
結構調整也是同樣道理。切分的依據始終是目的與依賴,不能只用「功能」或「重構」的分類來決定。
昨天決定哪些地方需要改,今天則是把這些修改組織成可理解的單位。清楚的邊界,讓後來的人在需要保留、撤回或手動調整時,不必先重新拆解整批工作。
提交訊息留下當次理由,文件留存長期脈絡
提交訊息必須說明這次修改的意圖。「新增付款狀態」只交代了局部改動;「支援部分退款,並維持售後追蹤資格」則讓人明白,為什麼這次需要同步調整排程。
提交訊息負責交代當下修改的理由與需求連結,讓後人不用在漫長的差異裡猜測當初的動機。但如果涉及更長遠的業務規則取捨,或需要記錄為什麼不採用其他方案,則超出了單一提交訊息該承載的範圍。
提交的邊界,決定後來的人如何理解與處理這次修改。把目的不同的變更分清楚,把必須一起成立的修改留在一起,歷史才有助於下一次判斷。
「這個提交叫『新增退款狀態』,怎麼連簡訊套件都換了?」
「順手。」
「現在想撤掉套件更換,要怎麼拆?」
「……這次就沒那麼順手了。」![]()